package ws

import (
	"errors"
	"sync"
	"time"
)

type WSClientManager interface {
	RegisteClient(username string, client *Client) error
	UnRegisteClient(username string, client *Client) error
	BroadcastMsg(username string, msg string, isSelf bool) error
}

type DefaultClientManager struct {
	Clients           map[string][]*Client
	rwLock            *sync.RWMutex
	onlineMsgChan     chan int
	onlineListMsgChan chan int
}

func NewDefaultClientManager() *DefaultClientManager {
	manager := &DefaultClientManager{
		Clients:           map[string][]*Client{},
		rwLock:            &sync.RWMutex{},
		onlineMsgChan:     make(chan int),
		onlineListMsgChan: make(chan int),
	}
	// 监听
	go manager.listenOnline()
	return manager
}
func (m *DefaultClientManager) listenOnline() {
	for {
		select {
		case <-m.onlineListMsgChan:
			clientNames := make([]string, 0)
			for k, _ := range m.Clients {
				clientNames = append(clientNames, k)
			}

			msg := Message{
				"cmdType":    0,
				"onlineList": clientNames,
				"type":       3,
				"sendTime":   time.Now().Format("2006-01-02 15:04:05"),
			}

			msgStr := msg.String()

			for _, v := range m.Clients {
				if len(v) == 0 {
					continue
				}
				for _, c := range v {
					c.Write(msgStr)
				}
			}

		case <-m.onlineMsgChan:
			msg := Message{
				"cmdType":  0,
				"online":   len(m.Clients),
				"type":     2,
				"sendTime": time.Now().Format("2006-01-02 15:04:05"),
			}

			msgStr := msg.String()

			for _, v := range m.Clients {
				if len(v) == 0 {
					continue
				}
				for _, c := range v {
					c.Write(msgStr)
				}
			}

		case <-time.After(time.Millisecond * 2000):
		}
	}
}

func (m *DefaultClientManager) RegisteClient(username string, client *Client) error {
	m.rwLock.Lock()
	defer m.rwLock.Unlock()

	cs, ok := m.Clients[username]
	if !ok {
		cs = make([]*Client, 0)
	}
	m.Clients[username] = append(cs, client)

	m.onlineMsgChan <- 1
	m.onlineListMsgChan <- 1
	return nil
}

func (m *DefaultClientManager) UnRegisteClient(username string, client *Client) error {
	m.rwLock.Lock()
	defer m.rwLock.Unlock()

	cs, ok := m.Clients[username]
	if !ok {
		return errors.New("client is not found")
	}
	var index int = -1
	for i, c := range cs {
		if client == c {
			index = i
			break
		}
	}
	if len(cs) == 1 {
		delete(m.Clients, username)
	} else {
		if index == len(cs)-1 {
			m.Clients[username] = cs[:index]
		} else {
			m.Clients[username] = append(cs[:index], cs[index+1])
		}
	}

	m.onlineMsgChan <- 1
	m.onlineListMsgChan <- 1
	return nil
}

func (m *DefaultClientManager) BroadcastMsg(username string, msg string, isSelf bool) error {
	m.rwLock.RLock()
	defer m.rwLock.RUnlock()

	for k, v := range m.Clients {
		if k == username {
			if isSelf {
				err := WriteMsg(v, msg)
				if err != nil {
					return err
				}
			}
		} else {
			if !isSelf {
				err := WriteMsg(v, msg)
				if err != nil {
					return err
				}
			}
		}
	}

	return nil
}

func WriteMsg(cs []*Client, msg string) error {

	for _, c := range cs {
		err := c.Write(msg)
		if err != nil {
			return err
		}
	}
	return nil
}
